/******************************************************************************* * Copyright (c) 2009, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation ******************************************************************************/ package org.eclipse.ui.internal.statushandlers; import java.io.IOException; import java.io.InputStream; import java.util.Map; import org.eclipse.jface.action.ContributionItem; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.DialogTray; import org.eclipse.jface.dialogs.ErrorSupportProvider; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.Policy; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.ui.statushandlers.AbstractStatusAreaProvider; import org.eclipse.ui.statushandlers.StatusAdapter; /** * This class is responsible for displaying the support area on the right * side of the status dialog. */ public class SupportTray extends DialogTray implements ISelectionChangedListener { private Map dialogState; /** * @param dialogState * @param listener */ public SupportTray(Map dialogState, Listener listener) { this.closeListener = listener; this.dialogState = dialogState; this.hideSupportButtons = getBooleanValue(IStatusDialogConstants.HIDE_SUPPORT_BUTTON); this.lastSelectedStatus = getCurrentStatusAdapter(); } private IContributionItem closeAction; private Listener closeListener; private boolean hideSupportButtons; private Image normal; private Image hover; /** * This composite occupies the whole space that is available to the support * tray. It has hardcoded layout behavior to protect the dialog. */ private Composite supportArea; private Composite supportAreaContent; private StatusAdapter lastSelectedStatus; private AbstractStatusAreaProvider userSupportProvider; /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets.Composite) */ protected Control createContents(Composite parent) { Composite container = new Composite(parent, SWT.NONE); // nothing to display. Should never happen, cause button is disabled // when nothing to display. if (providesSupport(getCurrentStatusAdapter()) == null && getBooleanValue(IStatusDialogConstants.TRAY_OPENED)) { } GridLayout layout = new GridLayout(); layout.marginWidth = layout.marginHeight = 0; layout.verticalSpacing = 0; container.setLayout(layout); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); container.setLayoutData(layoutData); container.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { destroyImages(); } }); if (!hideSupportButtons) { ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); toolBarManager.createControl(container); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_END); gd.grabExcessHorizontalSpace = true; toolBarManager.getControl().setLayoutData(gd); Label separator = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL); gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.heightHint = 1; separator.setLayoutData(gd); createActions(); toolBarManager.add(closeAction); toolBarManager.update(true); } supportArea = new Composite(container, SWT.NONE); layout = new GridLayout(); layout.marginWidth = layout.marginHeight = 0; layout.verticalSpacing = 0; supportArea.setLayout(layout); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL); gd.horizontalSpan = 1; gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true; supportArea.setLayoutData(gd); if (lastSelectedStatus != null) createSupportArea(supportArea, lastSelectedStatus); Point shellSize = supportArea.getShell().getSize(); Point desiredSize = supportArea.getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); if(desiredSize.y > shellSize.y){ supportArea.getShell().setSize(shellSize.x, Math.min(desiredSize.y, 500)); } return container; } /** * Creates any custom needed by the tray, such as the close button. */ private void createImages() { Display display = Display.getCurrent(); int[] shape = new int[] { 3, 3, 5, 3, 7, 5, 8, 5, 10, 3, 12, 3, 12, 5, 10, 7, 10, 8, 12, 10, 12, 12, 10, 12, 8, 10, 7, 10, 5, 12, 3, 12, 3, 10, 5, 8, 5, 7, 3, 5 }; /* * Use magenta as transparency color since it is used infrequently. */ Color border = display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW); Color background = display .getSystemColor(SWT.COLOR_LIST_BACKGROUND); Color backgroundHot = new Color(display, new RGB(252, 160, 160)); Color transparent = display.getSystemColor(SWT.COLOR_MAGENTA); PaletteData palette = new PaletteData(new RGB[] { transparent.getRGB(), border.getRGB(), background.getRGB(), backgroundHot.getRGB() }); ImageData data = new ImageData(16, 16, 8, palette); data.transparentPixel = 0; // RAP [bm] owner drawn image replaced by static // normal = new Image(display, data); // normal.setBackground(transparent); // GC gc = new GC(normal); // gc.setBackground(background); // gc.fillPolygon(shape); // gc.setForeground(border); // gc.drawPolygon(shape); // gc.dispose(); normal = loadImage( display, "org/eclipse/ui/internal/statushandlers/close.gif" ); // hover = new Image(display, data); // hover.setBackground(transparent); // gc = new GC(hover); // gc.setBackground(backgroundHot); // gc.fillPolygon(shape); // gc.setForeground(border); // gc.drawPolygon(shape); // gc.dispose(); hover = loadImage( display, "org/eclipse/ui/internal/statushandlers/close_hover.gif" ); backgroundHot.dispose(); } // RAP [if] private static Image loadImage( Display display, String name ) { Image result = null; InputStream stream = SupportTray.class.getClassLoader().getResourceAsStream( name ); if( stream != null ) { try { result = new Image( display, stream ); } finally { try { stream.close(); } catch( IOException unexpected ) { throw new RuntimeException( "Failed to close image input stream", unexpected ); } } } return result; } // RAPEND /** * Creates any actions needed by the tray. */ private void createActions() { createImages(); closeAction = new ContributionItem() { public void fill(ToolBar parent, int index) { final ToolItem item = new ToolItem(parent, SWT.PUSH); item.setImage(normal); item.setHotImage(hover); item.setToolTipText(JFaceResources.getString("close")); //$NON-NLS-1$ item.addListener(SWT.Selection, closeListener); } }; } private void destroyImages() { if (normal != null) normal.dispose(); if (hover != null) hover.dispose(); } /** * Create the area for extra error support information. * * @param parent * A composite on which should be the support area created. * @param statusAdapter * StatusAdapter for which should be the support area * created. */ private void createSupportArea(Composite parent, StatusAdapter statusAdapter) { ErrorSupportProvider provider = getSupportProvider(); // default support area was disabled if (provider == null) return; if (supportAreaContent != null) supportAreaContent.dispose(); supportAreaContent = new Composite(parent, SWT.FILL); GridData supportData = new GridData(SWT.FILL, SWT.FILL, true, true); supportAreaContent.setLayoutData(supportData); if (supportAreaContent.getLayout() == null) { GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; supportAreaContent.setLayout(layout); // Give it a default // layout } if (provider instanceof AbstractStatusAreaProvider) { ((AbstractStatusAreaProvider) provider).createSupportArea( supportAreaContent, statusAdapter); } else { provider.createSupportArea(supportAreaContent, statusAdapter .getStatus()); } } public ErrorSupportProvider getSupportProvider() { ErrorSupportProvider provider = Policy.getErrorSupportProvider(); if (userSupportProvider != null) { provider = userSupportProvider; } if (getBooleanValue(IStatusDialogConstants.ENABLE_DEFAULT_SUPPORT_AREA) && provider == null) { provider = new StackTraceSupportArea(); } return provider; } private StatusAdapter getStatusAdapterFromEvent( SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection instanceof StructuredSelection) { StructuredSelection structuredSelection = (StructuredSelection) selection; Object element = structuredSelection.getFirstElement(); if (element instanceof StatusAdapter) { return (StatusAdapter) element; } } return null; } /** * Checks if the support dialog has any support areas. * * @param adapter * - a parameter for which we area checking the status adapter * @return true if support dialog has any support areas to display, false * otherwise */ public ErrorSupportProvider providesSupport(StatusAdapter adapter) { ErrorSupportProvider provider = getSupportProvider(); if (provider instanceof AbstractStatusAreaProvider) { AbstractStatusAreaProvider areaProvider = (AbstractStatusAreaProvider) provider; if (areaProvider.validFor(adapter)) { return areaProvider; } return null; } return provider; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event) { lastSelectedStatus = getStatusAdapterFromEvent(event); if (supportArea != null && !supportArea.isDisposed()) { if (lastSelectedStatus != null) { createSupportArea(supportArea, lastSelectedStatus); supportArea.layout(true); } } } /** * @return Returns the supportArea. */ public Composite getSupportArea() { return supportArea; } private boolean getBooleanValue(Object key) { Boolean b = (Boolean) dialogState.get(key); if (b == null) { return false; } return b.booleanValue(); } private StatusAdapter getCurrentStatusAdapter() { return (StatusAdapter) dialogState .get(IStatusDialogConstants.CURRENT_STATUS_ADAPTER); } }